package modelo;

import java.util.ArrayList;
import java.util.Iterator;

import titiritero.Dibujable;
import utilitarios.Direccion;
import utilitarios.PuntoXY;
import vistas.VistaAlgoTank;

public class TanqueAlgo extends Tanque implements JugadorObservado {
	
    private static int VIDAS_INICIALES = 5;
    
	private boolean haPerdido = false;
	private int vidas = VIDAS_INICIALES;
	private int puntos = 0;
	private int tanquesDestruidos = 0;
	private ArrayList<ObservadorDeJugador> observadores = new ArrayList<ObservadorDeJugador>();
	
	public TanqueAlgo(Escenario escenario, PuntoXY posicionInicial) {
		super(escenario);
		this.velocidadMovimiento = VELOCIDAD_MOVIMIENTO_MEDIA;
		this.setPosicion(posicionInicial);
		this.arma = new Ametralladora(escenario, posicionInicial);
	}
	
	public int getPuntos() {
		return this.puntos;
	}
	
	public int getTanquesDestruidos() {
	    return this.tanquesDestruidos;
	}
	
	protected void sumarUnTanqueDestruido() {
	    this.tanquesDestruidos += 1;
	    this.notificarObservadores();
	}
	
	protected void sumarPuntos(int puntosPorDestruccion) {
	    this.puntos += puntosPorDestruccion;
}

	public int getVidas() {
		return this.vidas;
	}

	private void quitarUnaVida() {
		if (this.vidas > 0) {
			this.vidas -= 1;
		} else {
			this.vidas = 0;
		}
	}
	
	protected void aumentarVelocidadDisparo(double valor) {
	    double nuevaVelocidadDisparo = this.getArma().getVelocidadDisparo() + valor;
	    this.getArma().setVelocidadDisparo(nuevaVelocidadDisparo);
	}

	public boolean haPerdido() {
		return this.haPerdido;
	}

	@Override
    public Dibujable crearDibujable() {
		VistaAlgoTank vistaAlgoTank = new VistaAlgoTank();
		vistaAlgoTank.setPosicionable(this);
		return vistaAlgoTank;
	}

	protected void aumentarVelocidadEn(double valor) {
		this.velocidadMovimiento += valor;
	}
	
	protected void aumentarResistenciaEn(double valor) {
		this.resistencia += valor;
	}	
	
	@Override
    public void vivir() {
		this.notificarObservadores();
		if (this.estaMoviendose) {
			for (double i = 1.0; i <= this.velocidadMovimiento; i++) {
				this.moverEnDireccion(this.direccion);
			}
		}
		if (this.debeDisparar) {
			this.disparar();
			this.debeDisparar = false;
		}

	}

	public void chocarConArma(Arma unArma) {
		this.arma = unArma;
		this.notificarObservadores();
		this.escenario.eliminarObjeto(unArma);
	}

	@Override
    public void chocarConAlgoTank(TanqueAlgo unTanque) {
		this.detener();
		unTanque.detener();
	}

	@Override
    public void chocarConTanqueEnemigo(TanqueEnemigo unTanque) {
		this.detener();
		unTanque.detener();
	}

	@Override
    public void chocarConProyectil(Proyectil unProyectil) {
		this.recibirDanio(unProyectil.getDanio());
		unProyectil.detener();
		unProyectil.morir();
	}

	@Override
    public void chocarConPared(Pared unaPared) {
		this.detener();
	}

	public void chocarConCuartel(Cuartel cuartel) {
		this.detener();		
	}

	protected void perder() {
		this.haPerdido = true;
		this.quitarUnaVida();
	}

	@Override
    protected void morir() {
		this.perder();
		this.escenario.eliminarObjeto(this);
	}

	@Override
    public void moverEnDireccion(Direccion direccion) {
		PuntoXY centroViejo = this.figura.getCentroMasa();
		PuntoXY centroNuevo = centroViejo.sumarDireccion(direccion);
		
		this.figura.setCentroMasa(centroNuevo); 
		if (!escenario.permiteMovimiento(this)) {
			this.figura.setCentroMasa(centroViejo);
			}
		
		else {
		    @SuppressWarnings("unchecked")
            ArrayList<Objeto> objetos = (ArrayList<Objeto>) this.escenario.getObjetos().clone();
            Iterator<Objeto> iterador = objetos.iterator();
    		while (iterador.hasNext()) {
    			Objeto objeto = iterador.next();
    			if ( (!this.equals(objeto) ) && (this.figura.estaSolapadoCon(objeto.getFigura()))) {
    				objeto.chocarConAlgoTank(this);
    				this.figura.setCentroMasa(centroViejo);
    				return;
    				}
    			}
		}

	}

	private void notificarObservadores() {
		for (ObservadorDeJugador o : this.observadores) {
			o.actualizarJugador();
		}
	}
	
    @Override
    public void quitarObservador(ObservadorDeJugador unObservador) {
        this.observadores.remove(unObservador);
    }

	@Override
	public void agregarObservador(ObservadorDeJugador unObservador) {
		this.observadores.add(unObservador);
	}

	protected void resetear() {
        this.haPerdido = false;
        this.tanquesDestruidos = 0;
        this.resistencia = 100;
    }
}
